package com.gao.config;

import com.gao.util.MyHandlerExceptionResovler;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;


/**
 * @author gao
 * @time 2020/05/29 18:30:23
 */
@Configuration
public class ShiroConfig {

    @Bean
    public HashedCredentialsMatcher hcm() {
        HashedCredentialsMatcher hcm = new HashedCredentialsMatcher();
        hcm.setHashAlgorithmName("MD5");
        hcm.setHashIterations(1024);
        return hcm;
    }

    @Bean
    public Realm realm(DataSource ds) {
        JdbcRealm jdbcRealm = new JdbcRealm();
        jdbcRealm.setDataSource(ds);
        // 重写SQL查询
        // 认证
        jdbcRealm.setAuthenticationQuery("SELECT password, salt FROM users WHERE username=?");
        // 根据用户名查询角色
        jdbcRealm.setUserRolesQuery("SELECT rname FROM u_r ur INNER JOIN users u ON ur.`uid` = u.`uid` INNER JOIN roles r ON ur.rid = r.rid AND username = ?");
        // 根据角色名查询权限
        jdbcRealm.setPermissionsQuery("SELECT pname FROM r_p rp INNER JOIN roles r ON rp.`rid` = r.`rid` INNER JOIN permissions p ON rp.`pid` = p.`pid` AND rname = ?");

        // 支持权限查询(必须配置该项，否则无法判断用户拥有的角色是否拥有某个权限)
        jdbcRealm.setPermissionsLookupEnabled(true);

        // 设置加密
        jdbcRealm.setSaltStyle(JdbcRealm.SaltStyle.COLUMN);
        jdbcRealm.setCredentialsMatcher(hcm());

        return jdbcRealm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(Realm realm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean sffb = new ShiroFilterFactoryBean();
        // 未通过认证时，会被重定向到以下url
        sffb.setLoginUrl("/view/login");
        // 未通过授权时，会被重定向到以下url
        sffb.setUnauthorizedUrl("/view/unauthorized");
        sffb.setSecurityManager(securityManager);

        Map<String, String> map = new HashMap<>();
        map.put("/logout", "logout");
        map.put("/**/login", "anon");
//        map.put("/view/order_list", "perms[order:find]");
//        map.put("/view/product_list", "perms[product:find]");
        map.put("/**", "authc");
        sffb.setFilterChainDefinitionMap(map);
        return sffb;
    }

    // 开启shiro注解
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }

    @Bean
    public MyHandlerExceptionResovler handlerExceptionResovler() {
        return new MyHandlerExceptionResovler();
    }
}